#ifndef _DYNAMIC_ARRAY_H_
#define _DYNAMIC_ARRAY_H_

#include "Array.h"
#include "Exception.h"

namespace MySTL
{

template < typename T >
class DynamicArray : public Array<T>
{
public:
	DynamicArray(int length);
	~DynamicArray();
	DynamicArray(const DynamicArray& obj);
	DynamicArray& operator =(const DynamicArray& obj);

	void resize(int length);
	int length() const;

protected:
	virtual T* copy(const DynamicArray& obj, int newLength = -1);
	virtual void init(T* array, int length);
	virtual void update(T* array, int length);

protected:
	int m_length;
};

template < typename T >
DynamicArray<T>::DynamicArray(int length)
{
	m_length = 0;

	if (length <= 0)
	{
		THROW_EXCEPTION(ParameterErrorException, "Param length error in DynamicArray<T>::DynamicArray(int length)");
	}

	init(new T[length], length);
}

template < typename T >
DynamicArray<T>::~DynamicArray()
{
	delete[] this->m_array;
	this->m_array = NULL;
}

template < typename T >
DynamicArray<T>::DynamicArray(const DynamicArray<T>& obj)
{
	m_length = 0;

	init(copy(obj), obj.m_length);
}

template < typename T >
DynamicArray<T>& DynamicArray<T>::operator =(const DynamicArray<T>& obj)
{
	if (this != &obj)
	{
		update(copy(obj), obj.m_length);
	}

	return *this;
}

template < typename T >
void DynamicArray<T>::resize(int length)
{
	if (length <= 0)
	{
		THROW_EXCEPTION(ParameterErrorException, "Param length error in void DynamicArray<T>::resize(int length)");
	}

	if (m_length != length)
	{
		update(copy(*this, length), length);
	}
}

template < typename T >
int DynamicArray<T>::length() const
{
	return m_length;
}

template < typename T >
T* DynamicArray<T>::copy(const DynamicArray<T>& obj, int newLength)
{
	newLength = (newLength > 0) ? newLength : obj.m_length;

	T* space = new T[newLength];

	if (NULL != space)
	{
		int len = (newLength > 0 && newLength < obj.m_length) ? newLength : obj.m_length;

		for (int i = 0; i < len; ++i)
		{
			space[i] = obj.m_array[i];
		}
	}

	return space;
}
template < typename T >
void DynamicArray<T>::init(T* array, int length)
{
	if (NULL != array)
	{
		this->m_array = array;
		this->m_length = length;
	}
	else
	{
		THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory to construct DynamicArray in void DynamicArray<T>::init(T* array, int length)");
	}
}

template < typename T >
void DynamicArray<T>::update(T* array, int length)
{
	if (NULL != array)
	{
		T* toDel = this->m_array;

		this->m_array = array;
		this->m_length = length;

		delete[] toDel;
	}
	else
	{
		THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory to construct DynamicArray in void DynamicArray<T>::update(T* array, int length)");
	}
}

}

#endif